package org.framework.core;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.framework.core.annotation.Component;
import org.framework.core.annotation.Controller;
import org.framework.core.annotation.Repository;
import org.framework.core.annotation.Service;
import org.framework.util.ClassUtil;
import org.framework.util.ValidationUtil;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author：LCJ
 * @Description：bean容器
 * @Date：Create in 23:08 2021/5/1 0001
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class BeanContainer {

    /**
     * 存放所有被注解标记的目标对象
     */
    private final Map<Class<?>, Object> beanMap = new ConcurrentHashMap<Class<?>, Object>();

    /**
     * 加载bean的注解列表
     */
    private static final List<Class<? extends Annotation>> BEAN_ANNOTATION
            = Arrays.asList(Component.class, Controller.class, Service.class, Repository.class);

    /**
     * 判断容器是否被加载过
     */
    private boolean loaded=false;

    public boolean isLoaded(){
        return loaded;
    }





    /**
     * 获取Bean容器实例
     * @return
     */
    public static BeanContainer getInstance(){
        return ContainerHolder.HOLDER.instance;
    }
    private enum ContainerHolder{
        HOLDER;
        private BeanContainer instance;
        ContainerHolder(){
            instance = new BeanContainer();
        }
    }

    /**
     * 扫描加载所有Bean
     */

    public synchronized void loadBeans(String packageName){
        //判断bean容器是否被加载过
        if(isLoaded()){
            log.warn("BeanContainer has been loaded");
            return;
        }
        Set<Class<?>> classSet = ClassUtil.extractPackageClass(packageName);
        if(ValidationUtil.isEmpty(classSet)){
            log.warn("extract nothing from packageName"+packageName);
            return;
        }
        for(Class<?> clazz: classSet){
            for(Class<? extends Annotation> annotation: BEAN_ANNOTATION){
                //如果类上面标记了定义的注解
                if(clazz.isAnnotationPresent(annotation)){
                    //将目标类本身作为键，目标类的实例作为值，放入到beanMap中
                    beanMap.put(clazz,ClassUtil.newInstance(clazz,true));
                }
            }
        }
        loaded=true;
    }
}
